#include "treerender.h"
#include <GL/glu.h>
#include "TreeMesh.h"
#include <qgl.h>

#define NUM_LEAVES 5
//#define PI 3.14
using namespace std;
TreeRender::TreeRender(Renderer *rend){
    mQuadric = gluNewQuadric();
    gluQuadricNormals(mQuadric, GL_SMOOTH);					// Generate Smooth Normals For The Quad
    gluQuadricTexture(mQuadric, GL_TRUE);
    render = rend;
    m_drawLeaves = true;
}
void TreeRender::drawTree(TreeGen3D *treegen, bool id_mode, int tree_color){
//TODO: fill this in before thursday
    float3 trans = -treegen->treeRoot->start;
    //glTranslatef(trans.x, trans.y, trans.z);

    if (!id_mode){
        if(treegen->m_mesh) {
            treegen->m_mesh->draw(!id_mode && m_drawLeaves);
        }
    }
    else{
        recurDraw(treegen->treeRoot, tree_color);
    }

}

void TreeRender::recurDraw(Bud *b, int tree_color){
    glColor3ub(tree_color, b->branchID/255, b->branchID%255);
    drawBranch(b->start,b->end,b->phi,b->theta,b->length,b->diameter/2.0);
    if(b->aux)
    {
        recurDraw(b->aux, tree_color);
    }
    else{
    }
    if(b->term)
    {
        recurDraw(b->term, tree_color);
    }


}
void TreeRender::recurDrawLeaf(Bud *b, bool flowers){
    if(b->aux)
        recurDrawLeaf(b->aux, flowers);
   else if(!flowers)
        drawBud(b, false);
    if(b->term)
        recurDrawLeaf(b->term, flowers);
    else if(flowers)
        drawFlower(b, true);
}


void TreeRender::animateTree(){}
//TODO: for shadow propagation, create a large grid first, a bud is stationary store it in as you go so for shadow propagation it's just a look up
void TreeRender::drawBranch(float3 start, float3 end, float phi, float theta, float length, float radius){
    phi *= 180.0/PI;
    theta *= 180.0/PI;
    glMatrixMode(GL_MODELVIEW);
    //temporary to put at origin.
    //glPushMatrix();
    //glTranslatef(-200,-5,-200);

    glPushMatrix();
    glTranslatef(start.x, start.y, start.z);
    glRotatef(theta,0, 1, 0);
    glRotatef(phi,0,0,1);
    //cout<<"theta in draw: "<<theta<<endl;
    glRotatef(-90, 1, 0, 0);
    //note cylinder might be rotated
    gluCylinder(mQuadric, radius, radius, length, 5, 1);//slices/stacks based on radius and length?
    glPopMatrix();

   /* glPushMatrix();
    glTranslatef(start.x, start.y, start.z);
    glRotatef(-90, 1, 0, 0);
    gluSphere(mQuadric, radius, 5, 5);
    glPopMatrix();*/

    glPushMatrix();
     glTranslatef(end.x, end.y, end.z);
     //glRotatef(-90, 1, 0, 0);
    gluSphere(mQuadric, radius, 5, 5);
    glPopMatrix();
    //glPopMatrix();
}
//use shadow maps for shadowing
//void TreeRender::drawLeaf(){}
void TreeRender::drawBud(Bud * b, bool term){
    //drawBranch(b->start, b->end, b->phi, b->theta, b->length, b->diameter);
    glMatrixMode(GL_MODELVIEW);

    glEnable(GL_BLEND);
    glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_TEXTURE_2D);
    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);

    for(int i = 0; i< NUM_LEAVES; i++){
        glPushMatrix();

        glTranslatef(b->end.x, b->end.y, b->end.z);
        if(term)
            glRotatef((b->rotleaf + ((float) i - NUM_LEAVES/2.0) /1.5)* 180.0 / 3.14, b->direction.x, b->direction.y, b->direction.z);
        else
            glRotatef((b->rotleaf + ((float) i - NUM_LEAVES/2.0) /1.5)* 180.0 / 3.14, b->auxDir.x, b->auxDir.y, b->auxDir.z);
        glScalef(5,5,5);

        glRotatef(b->theta*180.0 / 3.0, 0, 1, 0);
        //glRotatef(b->rotleaf * 180/3.14, 0,1,0);
        glRotatef((b->phi + ((float) i - NUM_LEAVES/2.0) / 5.0) * 180.0 / 3.14,0,0,1);
        glRotatef(((float) i - NUM_LEAVES/2.0) / 1.5 * 180.0 /7.0, 0,0,1 );
        //glRotatef(180,0,0,1);
        glTranslatef(0,.5,0);



        //glBindTexture(GL_TEXTURE_2D,leaf);

        glBegin(GL_QUADS);
        glTexCoord3f(0,0,b->darken);
        glNormal3f(-.3,0,.7);
        glVertex3f(-.5, -.5, 0);

        glTexCoord3f(1,0,b->darken);
        glNormal3f(.3,0,.7);
        glVertex3f(.5,-.5 ,0);

        glTexCoord3f(1,1,b->darken);
        glNormal3f(.3,0,.7);
        glVertex3f(.5,.5,0);

        glTexCoord3f(0,1,b->darken);
        glNormal3f(-.3,0,.7);
        glVertex3f(-.5,.5,0);

        //back

        glTexCoord3f(0,0,b->darken);
        glNormal3f(-.3,0,-.7);
        glVertex3f(-.5, -.5,0);

        glTexCoord3f(0,1,b->darken);
        glNormal3f(-.3,0,-.7);
        glVertex3f(-.5,.5,0);

        glTexCoord3f(1,1,b->darken);
        glNormal3f(.3,0,-.7);
        glVertex3f(.5,.5,0);

        glTexCoord3f(1,0,b->darken);
        glNormal3f(.3,0,-.7);
        glVertex3f(.5,-.5,0);

        glEnd();

        glPopMatrix();
    }
    glDisable(GL_BLEND);
    glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);


}
void TreeRender::drawFlower(Bud *b, bool term){
    glMatrixMode(GL_MODELVIEW);

    glEnable(GL_BLEND);
    glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_TEXTURE_2D);
  //  glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
 //   glBindTexture(GL_TEXTURE_2D,leaf);
    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
    int numLayers = 4;
    for(int j = 0; j < numLayers; j++){
        for(int i = 0; i< NUM_LEAVES; i++){
            glPushMatrix();
            glTranslatef(b->end.x, b->end.y, b->end.z);
            //if(term)
            //    glRotatef((b->rotleaf + ((float) i - NUM_LEAVES/2.0) /1.5)* 180.0 / 3.14, b->direction.x, b->direction.y, b->direction.z);
            //else
            //    glRotatef((b->rotleaf + ((float) i - NUM_LEAVES/2.0) /1.5)* 180.0 / 3.14, b->auxDir.x, b->auxDir.y, b->auxDir.z);


            //needs some work:
            glRotatef(b->theta*180.0 / 3.14, 0, 1, 0);
            glRotatef((b->phi * 180.0)/ 3.14,0,0,1);
            //switcht to be aligned on + y axis
            glRotatef(-90, 1, 0,0);
            //star rotation
            glRotatef(((float) i) / NUM_LEAVES * 360.0 + ((float) j)/ numLayers * 360.0/NUM_LEAVES, 0,0,1 );
            //folds it
            glRotatef((float) j / (float) numLayers * 25.0 + 20.0, 1,0,0);
            //glRotatef(45.0, 1, 0,0);
            glScalef(1.3,4,3);
            glTranslatef(0,0,.5);




            //glBindTexture(GL_TEXTURE_2D,leaf);

            glBegin(GL_QUADS);
            glTexCoord3f(0,0,b->darken);
            glNormal3f(0,1,0);
            glVertex3f(-.5, 0, -.5);

            glTexCoord3f(1,0,b->darken);
            glNormal3f(0,1,0);
            glVertex3f(.5,0 ,-.5);

            glTexCoord3f(1,1,b->darken);
            glNormal3f(0,1,0);
            glVertex3f(.5,0,.5);

            glTexCoord3f(0,1,b->darken);
            glNormal3f(0,1,0);
            glVertex3f(-.5,0,.5);

            //back

            glTexCoord3f(0,0,b->darken);
            glNormal3f(0,-1,0);
            glVertex3f(-.5, 0,-.5);

            glTexCoord3f(0,1,b->darken);
            glNormal3f(0,-1,0);
            glVertex3f(-.5,0,.5);

            glTexCoord3f(1,1,b->darken);
            glNormal3f(0,-1,0);
            glVertex3f(.5,0,.5);

            glTexCoord3f(1,0,b->darken);
            glNormal3f(0,-1,0);
            glVertex3f(.5,0,-.5);

            glEnd();

            glPopMatrix();
        }
    }
    glDisable(GL_BLEND);

    glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);






}
//Note that if we use dome caps for the internodes the min length of a branch coming off of it must
//be the internodes radius (or it won't be seen), could be remedied by using a flatter cap, sacrificing some smoothness
//Don't think it'll be a big issue though
